package com.grouuu.core 
{
	import away3d.animators.VertexAnimationSet;
	import away3d.animators.VertexAnimator;
	import away3d.cameras.Camera3D;
	import away3d.cameras.lenses.OrthographicLens;
	import away3d.cameras.lenses.OrthographicOffCenterLens;
	import away3d.containers.ObjectContainer3D;
	import away3d.controllers.HoverController;
	import away3d.core.partition.PointLightNode;
	import away3d.entities.Mesh;
	import away3d.events.AssetEvent;
	import away3d.library.AssetLibrary;
	import away3d.library.assets.AssetType;
	import away3d.lights.DirectionalLight;
	import away3d.loaders.misc.AssetLoaderContext;
	import away3d.loaders.parsers.MD2Parser;
	import away3d.materials.lightpickers.StaticLightPicker;
	import away3d.materials.methods.FilteredShadowMapMethod;
	import away3d.materials.TextureMaterial;
	import away3d.tools.helpers.MeshHelper;
	import away3d.tools.utils.Bounds;
	import away3d.utils.Cast;
	import com.grouuu.event.TimerEvent;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.geom.Utils3D;
	import flash.geom.Vector3D;
	import starling.core.Starling;
	import starling.events.TouchEvent;
	
	/**
	 * ...
	 * @author Grouuu
	 */
	public class SceneComposite extends SceneTile 
	{
		[Embed(source="../../../../media/models/ogre/ogre_diffuse.jpg")]
		public static var OgreDiffuse:Class;
		
		[Embed(source="../../../../media/models/ogre/ogre_normals.png")]
		public static var OgreNormals:Class;
		
		[Embed(source="../../../../media/models/ogre/ogre_specular.jpg")]
		public static var OgreSpecular:Class;
		
		[Embed(source="../../../../media/models/ogre/ogre.md2",mimeType="application/octet-stream")]
		public static var OgreModel:Class;
		
		public static var stateNames:Array = ["stand", "sniffsniff", "deathc", "attack", "crattack", "run", "paina", "cwalk", "crpain", "cstand", "deathb", "salute_alt", "painc", "painb", "flip", "jump"];
		
		public function SceneComposite() 
		{
			super();
		}
		
		protected var hoverController:HoverController;
		protected var light:DirectionalLight;
		protected var lightPicker:StaticLightPicker;
		protected var assetLoaderContext:AssetLoaderContext;
		protected var shadowMapMethod:FilteredShadowMapMethod;
		protected var container:ObjectContainer3D;
		
		override protected function initHero():void
		{
			super.initHero();
			
			hero.visible = false;
			
			//
			
			container = new ObjectContainer3D();
			container.rotationX = -45;
			
			Main.awayView.scene.addChild(container);
			
			light = new DirectionalLight(0, -1, 1);
			lightPicker = new StaticLightPicker([light]);
			Main.awayView.scene.addChild(light);
			
			assetLoaderContext = new AssetLoaderContext();
			assetLoaderContext.mapUrlToData("igdosh.jpg", new OgreDiffuse());
			
			AssetLibrary.loadData(new OgreModel(), assetLoaderContext, null, new MD2Parser());
			AssetLibrary.addEventListener(AssetEvent.ASSET_COMPLETE, onAssetComplete);
			
			shadowMapMethod = new FilteredShadowMapMethod(light);
			
			posHero = centerScene;
		}
		
		protected var animationSet:VertexAnimationSet;
		protected var mesh:Mesh;
		
		protected function onAssetComplete(event:AssetEvent):void
		{
			if (event.asset.assetType == AssetType.MESH)
			{
				mesh = event.asset as Mesh;
				
				Main.awayView.camera.z = -400;
				Main.awayView.camera.lookAt(new Vector3D());
				Main.awayView.camera.lens = new OrthographicLens();
				
				var material:TextureMaterial = mesh.material as TextureMaterial;
				material.specularMap = Cast.bitmapTexture(OgreSpecular);
				material.normalMap = Cast.bitmapTexture(OgreNormals);
				material.lightPicker = lightPicker;
				material.gloss = 30;
				material.specular = 1;
				material.ambientColor = 0x303040;
				material.ambient = 1;
				material.shadowMethod = shadowMapMethod;
				
				mesh.x = 0;
				mesh.y = 0;
				mesh.z = 0;
				mesh.castsShadows = true;
				
				container.addChild(mesh);
				
				var vertexAnimator:VertexAnimator = new VertexAnimator(animationSet);
				
				vertexAnimator.play(stateNames[0]);
				mesh.animator = vertexAnimator;
			}
			else if (event.asset.assetType == AssetType.ANIMATION_SET)
			{
				animationSet = event.asset as VertexAnimationSet;
			}
		}
		
		protected function heroLocalToGlobal():Point
		{
			var pos3D:Vector3D = Main.awayView.project(container.position);
			
			return new Point(pos3D.x, pos3D.y);
		}
		
		protected function heroGlobalToLocal(position:Point):Vector3D
		{
			var pos:Vector3D = Main.awayView.unproject(position.x, position.y);
			
			return pos;
		}
		
		override protected function setMove(globalPoint:Point):void
		{
			var localPoint:Point = quadTiles.globalToLocal(globalPoint);
			var heroPoint:Point = quadTiles.globalToLocal(posHero);
			
			var distance:Number = Point.distance(heroPoint, localPoint);
			
			nbStep = distance / SceneTile.MOVE_SPEED;
			
			stepMoveX = (localPoint.x - heroPoint.x) / nbStep;
			stepMoveY = (localPoint.y - heroPoint.y) / nbStep;
			
			var rotation:Number = (Math.atan2(globalPoint.x - posHero.x, globalPoint.y - posHero.y)) * (180 / Math.PI);
			
			mesh.rotationY = rotation * -1 + 90;
			
			var vertexAnimator:VertexAnimator = new VertexAnimator(animationSet);
			
			vertexAnimator.play(stateNames[7]);
			mesh.animator = vertexAnimator;
		}
		
		override protected function checkImpassable():Boolean
		{
			// TODO : calculer le width/height du mesh
			
			//var boundHeroX:Number = (moveX >= 0) ? hero.width / 2 : -hero.width / 2;
			//var boundHeroY:Number = (moveY >= 0) ? hero.height / 2 : -hero.height / 2;
			var boundHeroX:Number = 0;
			var boundHeroY:Number = 0;
			
			var mapPos:Point = quadTiles.globalToLocal(new Point(posHero.x + moveX + boundHeroX, posHero.y + moveY + boundHeroY));
			
			var idTileX:int = mapPos.x / SceneTile.TILE_WIDTH;
			var idTileY:int = mapPos.y / SceneTile.TILE_HEIGHT;
			
			idTileX -= getRenderTileX(originTileX);
			idTileY -= getRenderTileY(originTileY);
			
			indexRender = getIndexRender(idTileY, idTileX);
			
			tileGraphic = renderList[indexRender];
			
			if (!tileGraphic.isPassable)
			{
				var vertexAnimator:VertexAnimator = new VertexAnimator(animationSet);
				
				vertexAnimator.play(stateNames[0]);
				mesh.animator = vertexAnimator;
			}
			
			return tileGraphic.isPassable;
		}
		
		protected var oldPosMeshX:Number;
		protected var oldPosMeshY:Number;
		protected var posHero:Point;
		protected var newPosHero:Vector3D;
		
		override protected function moveHero():void
		{
			oldPosMeshX = posHero.x;
			oldPosMeshY = posHero.y;
			
			// TODO : mais comment une putain de constante (centerScene) peut être modifiée par magie comme ça ??
			
			centerScene = new Point(STAGE_W / 2, STAGE_H / 2);
			
			if (lockX)
			{
				posHero.x += moveX;
				
				newPosHero = heroGlobalToLocal(posHero);
				
				container.x = newPosHero.x;
				
				if (oldPosMeshX < centerScene.x && posHero.x >= centerScene.x)
				{
					container.x = 0;
					moveX += oldPosMeshX - centerScene.x;
					quadTiles.x -= moveX;
					lockX = false;
					
					posHero.x = centerScene.x;
				}
				else if (oldPosMeshX > centerScene.x && posHero.x <= centerScene.x)
				{
					container.x = 0;
					moveX -= centerScene.x - oldPosMeshX;
					quadTiles.x += moveX;
					lockX = false;
					
					posHero.x = centerScene.x;
				}
			}
			
			if (lockY)
			{
				posHero.y += moveY;
				
				newPosHero = heroGlobalToLocal(posHero);
				
				container.y = newPosHero.y;
				
				if (oldPosMeshY < centerScene.y && posHero.y >= centerScene.y)
				{
					container.y = 0;
					moveY += oldPosMeshY - centerScene.y;
					quadTiles.y -= moveY;
					lockY = false;
					
					posHero.y = centerScene.y;
				}
				else if (oldPosMeshY > centerScene.y && posHero.y <= centerScene.y)
				{
					container.y = 0;
					moveY -= centerScene.y - oldPosMeshY;
					quadTiles.y += moveY;
					lockY = false;
					
					posHero.y = centerScene.y;
				}
			}
			
			hero.x = posHero.x;
			hero.y = posHero.y;
			
			if (nbStep <= 1)
			{
				var vertexAnimator:VertexAnimator = new VertexAnimator(animationSet);
				
				vertexAnimator.play(stateNames[0]);
				mesh.animator = vertexAnimator;
			}
		}
		
		override public function update(event:TimerEvent):void
		{
			if (!mesh)
				return;
			
			super.update(event);
			
			Main.stage3DProxy.clear();
			Main.starling.nextFrame();
			Main.awayView.render();
			Main.stage3DProxy.present();
		}
	}
}